#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <strings.h>



#include <sys/types.h>         
#include <sys/socket.h>
#include <pthread.h>
#include <signal.h>



#define SPORT 40000
#define SIP "0.0.0.0"

//封装应用层数据
typedef struct 
{
	unsigned int stu_num;
	char stu_name[50];
	
} data;
void print_err(char *str,int line,int err_no){
	printf("%d,%s:%s\n",line,str,strerror(err_no));
	exit(-1);

}

int cfd=-1; //存放与连接客户端通信的通信描述符
//次线程接收客户端数据
void *pth_fun(void *pth_arg){
	int ret=0;
	data stu_data={0};

	while(1){

		bzero(&stu_data,sizeof(stu_data));
		ret=recv(cfd,&stu_data,sizeof(stu_data),0);
		if(ret ==-1) print_err("receive err:",__LINE__,errno);
		else if(ret>0){
			printf("stu number=%d\n",ntohl(stu_data.stu_num) );
			printf("stu_name=%s\n",stu_data.stu_name) ;
		}
	}
	

}

void signal_fun(int signo){
	printf("signo=%d\n",signo);
	if(signo == SIGINT){
		//close(cfd);
		int ret=-1;
		char bye[]="\nserver close\n";
		ret=send(cfd,(void *) &bye,sizeof(bye),0);
		if(ret ==-1) print_err("send err:",__LINE__,errno);
		shutdown(cfd,SHUT_RDWR);
		exit(0);
	}

}


int main(){
	int ret=-1;
	int sockfd=-1;
	signal(SIGINT,signal_fun);
	//创建使用TCP协议通信的套接字文件
	sockfd=socket(PF_INET,SOCK_STREAM,0);
	if(sockfd ==-1)print_err("socket err:",__LINE__,errno);
	printf("sockfd=%d\n",sockfd);

	//调用Bind绑定套接字文件 ip/端口
	struct sockaddr_in saddr;

	saddr.sin_family=AF_INET;
	saddr.sin_port=htons(SPORT);
	saddr.sin_addr.s_addr=inet_addr(SIP);

	ret =bind(sockfd,(struct sockaddr *)&saddr,sizeof(saddr));
	if(ret ==-1) print_err("bind err:",__LINE__,errno);
	printf("ret=%d\n",ret );

	//将主动套接字文件描述符转为被动描述符
	ret=listen(sockfd,3);
	if(ret ==-1) print_err("listen err:",__LINE__,errno);

	//调用accept函数，被动监听客户端连接
	


	struct sockaddr_in clnaddr={0}; //存放客户端的ip和端口
	int clnaddr_size=sizeof(clnaddr);
	cfd=accept(sockfd,(struct sockaddr *)&clnaddr,&clnaddr_size);
	if(cfd ==-1) print_err("accept err:",__LINE__,errno);
   //打印连接客户端的端口和ip,一定要进行端序转换
	printf("cln_port= %d, cln_ip=%s\n", ntohs(clnaddr.sin_port), inet_ntoa(clnaddr.sin_addr));

	pthread_t tid;
	//次线程接收用户发送的数据
	pthread_create(&tid,NULL,pth_fun,NULL);

	data stu_data={0};
	unsigned int tmp_num=0;

	while(1){
		//获取学生学号，但是需要从主机端序转换为网络端序
		
		printf("input stu_num:\n");
		scanf("%d",&tmp_num);
		stu_data.stu_num=htonl(tmp_num);

		//char的数据不需要进行端序转换
		printf("input stu_name\n");
		scanf("%s",stu_data.stu_name);

		ret=send(cfd,(void *) &stu_data,sizeof(stu_data),0);
		if(ret ==-1) print_err("send err:",__LINE__,errno);


	}

	return 0;
}



